#ifndef STEINER_POINT2D_H
#define STEINER_POINT2D_H

#include <memory>

namespace STEINER {

template <typename T>
class Point2D
{
public:
    using SPtr = std::shared_ptr<Point2D<T> >;

    Point2D() {}

    Point2D(const T _x, const T _y) : x(_x), y(_y) {}

    virtual ~Point2D() {}

    bool operator==(const Point2D& that) {
        return x == that.x && y == that.y;
    }

    bool operator<(const Point2D& that) {
        if (*this == that) {
            return false;
        }
        if (GetAbs() != that.GetAbs()) {
            return GetAbs() < that.GetAbs();
        }
        if (GetAbsX() != that.GetAbsX()) {
            return GetAbsX() < that.GetAbsX();
        }
        if (GetAbsY() != that.GetAbsY()) {
            return GetAbsY() < that.GetAbsY();
        }
        if (GetX() != that.GetX()) {
            return GetX() < that.GetX();
        }
        return GetY() <= that.GetY();
    }

    T GetAbs() const {
        return std::abs(x) + std::abs(y);
    }

    T GetAbsX() const {
        return std::abs(x);
    }

    T GetAbsY() const {
        return std::abs(y);
    }

    T GetX() const {
        return x;
    }

    T GetY() const {
        return y;
    }


protected:
    T x;
    T y;
};

template <typename T>
inline bool ComparePointSPtrOfK(const std::shared_ptr<Point2D<T> >& left, const std::shared_ptr<Point2D<T> >& right) {
    return *left < *right;
}

}




#endif
